﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TUIOsharp;
using TUIOsharp.DataProcessors;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Windows;
using System.Runtime.InteropServices;
using System.Diagnostics;

using ORT;
//using Lean.Touch;
//#if TOUCHSCRIPT_TUIO
//#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_IOS || UNITY_ANDROID
using TouchScript.InputSources;
//#endif
//#endif
public class Main : MonoBehaviour
{
  
    public int tuioPort = 3333;
    public Text infoText;
  
  
    private bool dataReady = false;

    //事件通知
    //marker新增
    public System.Action<List<Marker>> MarkerAddCallback = delegate { };
    //marker移动
    public System.Action<List<Marker>> MarkerUpdateCallback = delegate { };
    //marker结束
    public System.Action<List<Marker>> MarkerRemoveCallback = delegate { };

    private TuioServer mServer;
    private ObjectProcessor mObjectProcessor;
    //保存当前所有marker的字典： guid - marker
    private Dictionary<int, Marker> mMarkerDictionary = new Dictionary<int, Marker>();

    float screenWidth = 1920f;
    float middleX=1920f/2;
    float middleY=1080/2;
    float screenHeight = 1080f;
    public Canvas thisCanvas;
    public Camera mainCamera;

    private static readonly object locker = new object();

    List<Marker> addMarkers = new List<Marker>();
    List<Marker> updateMarkers = new List<Marker>();
    List<Marker> removeMarkers = new List<Marker>();
    List<Marker> expireMarkers = new List<Marker>();
    
    //待处理的tuio消息
    List<TUIOMsg> tuioMsgList = new List<TUIOMsg>();

   

    [SerializeField]
    public int displayIndex=0;        //显示器编号
    void Awake()
    {

    }

    private void handleObjEvent(int id, bool isShow)
    { 
           UnityEngine.Debug.Log(DateTime.Now.ToString("handleObjEvent") + "   isShow" + isShow);
        TestCircle circle=Recognition.instance.circleDic[id];
        if(isShow)
        {
             lock (locker)
             {

                tuioMsgList.Add(new TUIOMsg(circle.circlePos.x+middleX, circle.circlePos.y+middleY,circle.curAngle,id, 1, 1));
            }
        }
        else
        {
             lock (locker)
             {
                tuioMsgList.Add(new TUIOMsg(circle.circlePos.x, circle.circlePos.y,circle.curAngle,id, 1,  2));
            }
        }
    }

    private void handleObjRotate(int id, float angle)
    {
           UnityEngine.Debug.Log(DateTime.Now.ToString("handleObjRotate") + "   angle" + angle);
         TestCircle circle= Recognition.instance.circleDic[id];
         lock (locker)
             {

                tuioMsgList.Add(new TUIOMsg(circle.circlePos.x+middleX, circle.circlePos.y+middleY,angle,id, 1, 1));
            }
    }

    protected void OnEnable()
    {
        screenWidth = Screen.width;
        screenHeight = Screen.height;
        Connect();
        Recognition.instance.mRecognitionID=handleObjEvent;
         Recognition.instance.mRecognitionIDAngle=handleObjRotate;
    }

    protected void OnDisable()
    {
        Disconnect();
    }

    //监听端口
    private void Connect()
    {
        if (!Application.isPlaying) return;

     

        if (mServer != null) Disconnect();

        mServer = new TuioServer(tuioPort);
        mServer.Connect();
        InitProcessor();
#if TOUCHSCRIPT_TUIO
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_IOS || UNITY_ANDROID
        RayionTuioInput tuioinput = FindObjectOfType<RayionTuioInput>();
        if (tuioinput != null)
        {
            tuioinput.OnConnect(mServer);
        }
#endif
#endif
    }

    //停止监听
    private void Disconnect()
    {
     

        if (mServer != null)
        {
            mServer.RemoveAllDataProcessors();
            mServer.Disconnect();
            mServer = null;

#if TOUCHSCRIPT_TUIO
#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_IOS || UNITY_ANDROID
            RayionTuioInput tuioinput = FindObjectOfType<RayionTuioInput>();
            if (tuioinput != null)
            {
                tuioinput.OnDisconnect();
            }
#endif
#endif
        }
        mMarkerDictionary.Clear();
    }


    public class PtoP_Length
    {
        public float distances { get; set; }
        public Vector2 FirstPosition { get; set; }
        public Vector2 SecondPosition { get; set; }
    }


    //添加tuio解析器
    private void InitProcessor()
    {
        if (mServer == null) return;
        mObjectProcessor = new ObjectProcessor();
        mObjectProcessor.ObjectAdded += OnObjectAdded;
        mObjectProcessor.ObjectUpdated += OnObjectUpdated;
        mObjectProcessor.ObjectRemoved += OnObjectRemoved;
        mServer.AddDataProcessor(mObjectProcessor);
    }


    private void RemoveExpiredMarker()
    {
        expireMarkers.Clear();
        foreach (var item in mMarkerDictionary)
        {
            if (item.Value.IsExpired())
            {
                expireMarkers.Add(item.Value);
            }
        }
        foreach (var item in expireMarkers)
        {
            mMarkerDictionary.Remove(item.guid);
        }
    }


    
    private void OnObjectAdded(object sender, TuioObjectEventArgs e)
    {
        var entity = e.Object;
      //  Debug.LogFormat("Marker Add ,Class = {0} ,ID = {1}", entity.ClassId, entity.Id);
        lock (locker)
        {
            tuioMsgList.Add(new TUIOMsg(entity.X, entity.Y, entity.Angle, entity.Id, entity.ClassId, 0));
        }
    }

    private void OnObjectUpdated(object sender, TuioObjectEventArgs e)
    {
        var entity = e.Object;
        // Debug.LogFormat("Marker Update ,Class = {0} ,ID = {1}", entity.ClassId, entity.Id);
          UnityEngine.Debug.LogFormat("Marker Update ,x = {0} ,y = {1} ,rotate = {2}", entity.X, entity.Y, entity.Angle);
        lock (locker)
        {
            tuioMsgList.Add(new TUIOMsg(entity.X, entity.Y, entity.Angle, entity.Id, entity.ClassId, 1));
        }
    }


    private void OnObjectRemoved(object sender, TuioObjectEventArgs e)
    {
        var entity = e.Object;
        //Debug.LogFormat("Marker Remove ,Class = {0} ,ID = {1}", entity.ClassId, entity.Id);
        lock (locker)
        {
            tuioMsgList.Add(new TUIOMsg(entity.X, entity.Y, entity.Angle, entity.Id, entity.ClassId, 2));
        }
    }
    //tuio的标准化坐标换算到屏幕坐标
    private Vector2 Tuio2Screen(float x, float y)
    {
        string info = string.Format("Tuio2Screen x={0} y={1}", x * screenWidth, (1.0f - y) * screenHeight);
        // Debug.Log(info);
        // Debug.Log(screenWidth);
        Vector2 screenPos = new Vector2(x * screenWidth, (1.0f - y) * screenHeight);
        return screenPos;
    }

    //更新ui信息
    void UpdateInfo()
    {
        if (infoText.gameObject.activeInHierarchy)
        {

            string info = string.Format("令牌数量 = {0}\n", mMarkerDictionary.Count);
            info += "-编码--位置--角度-\n";
            foreach (var item in mMarkerDictionary)
            {
                info += string.Format("    {0}     ({1},{2})  {3}\n", item.Value.code, item.Value.position.x.ToString("F0"), item.Value.position.y.ToString("F0"), item.Value.angle.ToString("F0"));
            }
            //Debug.Log(info);
            infoText.text = info;

        }
        else
        {
           
        }
    }

   
    // Start is called before the first frame update
    void Start()
    {

     
    }

    // Update is called once per frame
    void Update()
    {
       // UnityEngine.Debug.Log("dataReady=" + dataReady);
        if (!dataReady) return;
        HandleTUIOMsg();
        RemoveExpiredMarker();

        if (addMarkers.Count > 0)
        {
            MarkerAddCallback(addMarkers);
        }
        if (updateMarkers.Count > 0)
        {
             UnityEngine.Debug.Log("updateMarkers.Count=" + updateMarkers.Count);
            MarkerUpdateCallback(updateMarkers);
        }
        if (removeMarkers.Count > 0)
        {
            MarkerRemoveCallback(removeMarkers);
        }
        if (expireMarkers.Count > 0)
        {
            MarkerRemoveCallback(expireMarkers);
        }
        UpdateInfo();
    }

    void HandleTUIOMsg()
    {
        List<TUIOMsg> msgs;
        lock (locker)
        {
            msgs = new List<TUIOMsg>(tuioMsgList);
            tuioMsgList.Clear();
        }

        addMarkers.Clear();
        updateMarkers.Clear();
        removeMarkers.Clear();
        foreach (var msg in msgs)
        {
            switch (msg.tuio_eventType)
            {
                case 0:
                case 1:
                    {
                        if (mMarkerDictionary.ContainsKey(msg.tuio_id) == false)
                        {   

                             Marker m = new Marker(new Vector2(msg.tuio_x, msg.tuio_y), MathUtil.StandardizeAngle(Mathf.Rad2Deg * msg.tuio_angle), msg.tuio_classID, msg.tuio_id);
                            //Marker m = new Marker(Tuio2Screen(msg.tuio_x, msg.tuio_y), MathUtil.StandardizeAngle(Mathf.Rad2Deg * msg.tuio_angle), msg.tuio_classID, msg.tuio_id);
                            mMarkerDictionary.Add(m.guid, m);
                          //  UnityEngine.Debug.Log("add Markers "+  msg.tuio_angle);
                            addMarkers.Add(m);
                        }
                        else
                        {
                            Marker m = mMarkerDictionary[msg.tuio_id];
                             m.Update(new Vector2(msg.tuio_x, msg.tuio_y), MathUtil.StandardizeAngle(Mathf.Rad2Deg * msg.tuio_angle));
                            //m.Update(Tuio2Screen(msg.tuio_x, msg.tuio_y), MathUtil.StandardizeAngle(Mathf.Rad2Deg * msg.tuio_angle));
                            updateMarkers.Add(m);
                          //  UnityEngine.Debug.Log("update Markers x "+ msg.tuio_x+" y "+ msg.tuio_y);

                            // Debug.Log("updateMarkers");
                        }

                    }
                    break;
                case 2:
                    {
                        if (mMarkerDictionary.ContainsKey(msg.tuio_id))
                        {
                            Marker m = mMarkerDictionary[msg.tuio_id];
                            mMarkerDictionary.Remove(msg.tuio_id);
                              //UnityEngine.Debug.Log("Remove Markers "+  msg.tuio_id);


                            removeMarkers.Add(m);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }

   
 
    string SanJiao(double b1, double b2, double b3)
    {
        string ss = "";
        //首先判断能否组成三角形
        if (b1 + b2 > b3 && b1 + b3 > b2 && b2 + b3 > b1)
        {
            //return "可以组成三角形";
            //判断是怎样的三角形，并输出
            if (b1 == b2 && b2 == b3)
            {
                ss = "是等边三角形";
            }
            else if (b1 == b2 || b2 == b3 || b1 == b3)
                ss = "是等腰三角形";
            else if (b1 * b1 + b2 * b2 == b3 * b3 || b1 * b1 + b3 * b3 == b2 * b2 || b3 * b3 + b2 * b2 == b1 * b1)
                ss = "是直角三角形";
        }
        else
            ss = "输入的三边不能组成三角形";
 
        return ss;
    }
 
   
 
  

}

public class TUIOMsg
{
    public float tuio_x;
    public float tuio_y;
    public float tuio_angle;
    public int tuio_id;
    public int tuio_classID;
    //事件类型 0 = 新增， 1 = 更新， 2 = 结束
    public int tuio_eventType;

    public TUIOMsg(float _x, float _y, float _angle, int _id, int _classID, int _eventType)
    {
        tuio_x = _x;
        tuio_y = _y;
        tuio_angle = _angle;
        tuio_id = _id;
        tuio_classID = _classID;
        tuio_eventType = _eventType;
    }
}
